#include "RtpTest.h"
#include "ortp/ortp.h"
#include <memory.h>
#include <fstream>
#include <string>
#include <time.h>

CPPUNIT_TEST_SUITE_REGISTRATION(CRtpTestCase);

void CRtpTestCase::setUp()
{
//  ortp_init();
//  ortp_scheduler_init();
//  ortp_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR);
  m_rtp = new CRtp();
  m_rtp2 = new CRtp();
}

void CRtpTestCase::tearDown()
{
  delete m_rtp2;
  delete m_rtp;
//  ortp_exit();
}

static const char *AUX_FILENAME = "test_samples";
static const char *OUT_FILENAME = "samples.out";

static const size_t PAYLOAD_SIZE = 160;
static const unsigned char PAYLOAD_TYPE = 0; // PCM mu-law
static const unsigned int TIMESTAMP_INC = 160;
static const int MAX_PACKETS = 10;
static const timespec SLEEP_TIME = { 0, 62500000 };
static const unsigned short LOCAL_PORT = 45000;
static const unsigned short REMOTE_PORT = 5000;
static const std::string REMOTE_ADDR = "192.168.20.1";

void CRtpTestCase::BindPortTest()
{
  // nabindovani na port, ktery by mel byt volny
  CPPUNIT_ASSERT(m_rtp2->BindPort(LOCAL_PORT));
  // nabindovani na ten samy port, nemelo by se podarit
  CPPUNIT_ASSERT(!m_rtp->BindPort(LOCAL_PORT));
}

void CRtpTestCase::ConnectTest()
{
  CPPUNIT_ASSERT(m_rtp->BindPort(LOCAL_PORT));
  CPPUNIT_ASSERT(m_rtp->Connect(REMOTE_ADDR, REMOTE_PORT));
}

void CRtpTestCase::SendPacketTest()
{
  CPPUNIT_ASSERT(m_rtp->BindPort(LOCAL_PORT));
  CPPUNIT_ASSERT(m_rtp->Connect(REMOTE_ADDR, REMOTE_PORT));

  std::fstream fData;
  fData.open(AUX_FILENAME, std::ios::in | std::ios::binary);
  CPPUNIT_ASSERT(fData.is_open());

  CPPUNIT_ASSERT(m_rtp->SetSendPayloadType(PAYLOAD_TYPE));

  char cBuffer[PAYLOAD_SIZE];
  int i = 0;
  unsigned int ts = 0;
  while(fData.good() && i < MAX_PACKETS) {
    fData.read(cBuffer, PAYLOAD_SIZE);
    if(fData.gcount() > 0) {
      CPPUNIT_ASSERT(m_rtp->SendPacket(cBuffer, fData.gcount(), ts));
      //m_rtp->SendPacket(cBuffer, fData.gcount());
      nanosleep(&SLEEP_TIME, NULL);
      if(i == 96)
        sleep(5);
      i++;
      ts += TIMESTAMP_INC;
    }
  }
  fData.close();
}

void CRtpTestCase::ReadPacketTest()
{
  CPPUNIT_ASSERT(m_rtp->BindPort(LOCAL_PORT));
  CPPUNIT_ASSERT(m_rtp2->BindPort(REMOTE_PORT));
  
  CPPUNIT_ASSERT(m_rtp->Connect("127.0.0.1", REMOTE_PORT));
  CPPUNIT_ASSERT(m_rtp2->Connect("127.0.0.1", LOCAL_PORT));

  std::fstream fInput, fOutput;
  fInput.open(AUX_FILENAME, std::ios::in | std::ios::binary);
  fOutput.open(OUT_FILENAME, std::ios::out | std::ios::binary);
  CPPUNIT_ASSERT(fInput.is_open());
  CPPUNIT_ASSERT(fOutput.is_open());

  CPPUNIT_ASSERT(m_rtp->SetSendPayloadType(PAYLOAD_TYPE));
  CPPUNIT_ASSERT(m_rtp2->SetRecvPayloadType(PAYLOAD_TYPE));

  char cBuffer[PAYLOAD_SIZE];
  std::string strPacket;
  int _iResult;
  fd_set _read, _write;
  timeval _timeout = {1, 0};

  m_rtp2->Init(&_read, &_write);

  int i = 0;
  unsigned int ts = 0;
  while(fInput.good() && i < MAX_PACKETS) {
    fInput.read(cBuffer, PAYLOAD_SIZE);
    if(fInput.gcount() >  0) {
      CPPUNIT_ASSERT(m_rtp->SendPacket(cBuffer, fInput.gcount(), ts));
      nanosleep(&SLEEP_TIME, NULL);

      _timeout.tv_sec = 1;
      FD_ZERO(&_read);
      FD_ZERO(&_write);
      m_rtp2->SetFd();
      _iResult = select(FD_SETSIZE, &_read, &_write, NULL, &_timeout);
      if(_iResult > 0) {
        while(m_rtp2->ReadPacket(strPacket, TIMESTAMP_INC)) {
          fOutput.write(strPacket.c_str(), strPacket.size());
        }
      } else if(_iResult == 0) {
       // CPPUNIT_ASSERT(false);
      } else {
        CPPUNIT_ASSERT(0);
      }

      i++;
      ts += TIMESTAMP_INC;
    }
  }
  fInput.close();
  fOutput.close();
}

